package org.kitten.core.io;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.Collection;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.kitten.core.util.ErrorUtil;
import org.kitten.core.util.FileUtil;
import org.kitten.core.util.StringUtil;

public class FileHelper extends FileUtil {
	public final static boolean CONTINUE = true;
	public final static boolean BREAK = false;
	private static final Log logger = LogFactory.getLog(FileHelper.class);

	public static void appendMethodA(String fileName, String content) {
		RandomAccessFile randomFile = null;
		try {
			// 打开一个随机访问文件流，按读写方式
			randomFile = new RandomAccessFile(fileName, "rw");
			// 文件长度，字节数
			long fileLength = randomFile.length();
			// 将写文件指针移到文件尾。
			randomFile.seek(fileLength);
			randomFile.write(content.getBytes("UTF-8"));

		} catch (IOException e) {
			logger.error(ErrorUtil.getError(e));
		} finally {
			try {
				if (randomFile != null) {
					randomFile.close();
				}
			} catch (IOException e) {
				logger.error(ErrorUtil.getError(e));
			}
		}
	}

	/**
	 * 先清空文件夹,再删除文件夹本身 删除文件夹里面的所有文件,且包括倒数第一文件夹 e.g c:/fqf/34 34会被删.
	 * 
	 */
	public static void delFolder(String folder) {
		try {
			clearFolder(folder);
			File f = new File(folder);
			f.delete();
		} catch (Exception e) {
			logger.error(ErrorUtil.getError(e));
		}
	}

	public static void clearoneFolder(String path) {
		File file = new File(path);
		if (!file.exists()) {
			return;
		}
		file.delete();
	}

	/**
	 * 删除文件夹里面的所有文件,但不包括倒数第一文件夹 e.g c:/fqf/34 34不会被删.
	 * 
	 * @param path
	 *            String 文件夹路径 如 c:/fqf
	 */
	public static void clearFolder(String path) {
		File file = new File(path);
		if (!file.exists()) {
			return;
		}
		if (!file.isDirectory()) {
			return;
		}
		String[] tempList = file.list();
		File temp = null;
		for (int i = 0; i < tempList.length; i++) {
			if (path.endsWith(File.separator)) {
				temp = new File(path + tempList[i]);
			} else {
				temp = new File(path + File.separator + tempList[i]);
			}
			if (temp.isFile()) {
				temp.delete();
			}
			if (temp.isDirectory()) {
				clearFolder(path + "/" + tempList[i]); // 先删除文件夹里面的文件

				delFolder(path + "/" + tempList[i]); // 再删除空文件夹
			}
		}
	}

	/**
	 * 取得所有满足folderPatterns的目录.<br>
	 * 必须精确匹配pattern，找到满足条件的目录后不会递归该目录．
	 * 
	 * @param strPath
	 *            要搜索的根目录
	 * @param folderPatterns
	 *            目录名
	 * @return File集合
	 */
	@SuppressWarnings("unchecked")
	public static void getFolders(final Collection folders, String strPath,
			String[] folderPatterns, boolean recursive) {

		FileHelper.processFolders(strPath, folderPatterns,
				new IFolderProcessor() {
					public void processFolder(File f) {
						folders.add(f);
					}
				}, recursive);
	}

	/**
	 * 边遍历边处理目录.
	 * 
	 * @see #getFolders(String, String[])
	 * @param strPath
	 *            搜索的根目录
	 * @param folderPatterns
	 *            目录名，精确匹配．
	 * @param folderProcessor
	 *            处理目录的回调接口
	 */
	public static void processFolders(String strPath, String[] folderPatterns,
			IFolderProcessor folderProcessor, boolean recursive) {
		File f = new File(strPath);
		if (f.isDirectory()) {// 如果它是目录
			boolean match = false;
			String name = f.getName();
			for (int i = 0; i < folderPatterns.length; i++) {// 如果他自己就匹配
				if (name.equalsIgnoreCase(folderPatterns[i])) {
					folderProcessor.processFolder(f);
					match = true;
					break;
				}
			}
			if (!match || recursive) {// 如果他自己不匹配，则搜索他的孩子
				File[] fileList = f.listFiles();
				for (int i = 0; i < fileList.length; i++) {
					processFolders(fileList[i].getPath(), folderPatterns,
							folderProcessor, recursive);
				}
			}
		}

	}

	/**
	 * 根据文件后缀处理文件.
	 * 
	 * @param strPath
	 *            根目录名
	 * @param fileExts
	 *            文件后缀数组,null表示全部文件
	 * @param excludes
	 *            要排除的文件后缀，当fileExts为null有效。
	 * @param fileProcessor
	 * @param recursive
	 *            是否递归子目录
	 * @throws Exception
	 */
	public static void processFiles(String strPath, String[] fileExts,
			String[] excludes, IFileProcessor fileProcessor, boolean recursive)
			throws Exception {
		MyFilenameFilter mff = new MyFilenameFilter();
		mff.addExtensions(fileExts);
		mff.addExcludes(excludes);
		processFiles(strPath, mff, fileProcessor, recursive);
	}

	/**
	 * 根据自定义的FilenameFilter处理文件，推荐使用MyFilenameFilter.
	 * 
	 * @param strPath
	 *            根目录名
	 * @param mff
	 *            文件过滤器
	 * @param fileProcessor
	 * @param recursive
	 *            是否递归子目录
	 * @throws Exception
	 */
	public static void processFiles(String strPath, FilenameFilter mff,
			IFileProcessor fileProcessor, boolean recursive) throws Exception {
		File f = new File(strPath);
		if (!f.exists()) {
			return;
		}
		if (f.isDirectory()) {
			File[] fileList = f.listFiles(mff);
			for (int i = 0; i < fileList.length; i++) {
				if (recursive && fileList[i].isDirectory()) {
					processFiles(fileList[i].getAbsolutePath(), mff,
							fileProcessor, recursive);
				} else if (fileList[i].isFile()) {
					fileProcessor.processFile(fileList[i]);
				}
			}
		} else {
			fileProcessor.processFile(f);
		}
	}

	/**
	 * 取得具有指定后缀的文件集合,展示了本类中processFiles方法的强大功能。
	 * 
	 * @param files
	 * @param strPath
	 * @param fileExts
	 * @param excludes
	 * @param recursive
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static void getFiles(final Collection files, String strPath,
			String[] fileExts, String[] excludes, boolean recursive) {

		try {
			processFiles(strPath, fileExts, excludes, new IFileProcessor() {
				public void processFile(File f) {
					files.add(f);
				}
			}, recursive);
		} catch (Exception e) {
			logger.error(ErrorUtil.getError(e));
		}

	}

	/**
	 * 取得指定类型文件的文件个数。
	 * 
	 * @param strPath
	 * @param fileExts
	 * @param excludes
	 * @param recursive
	 * @return
	 */
	public static int getFileCount(String strPath, String[] fileExts,
			String[] excludes, boolean recursive) {

		final int[] fileCount = new int[] { 0 };
		try {
			processFiles(strPath, fileExts, excludes, new IFileProcessor() {
				public void processFile(File f) {
					fileCount[0]++;
				}
			}, recursive);
		} catch (Exception e) {
			logger.error(ErrorUtil.getError(e));
			return -1;
		}
		return fileCount[0];
	}

	/**
	 * 重命名
	 * 
	 * @param f
	 * @param newName
	 * @return
	 */
	public static boolean renameFile(File f, String newName) {
		String path = f.getParent();
		File newFile = new File(path + File.separator + newName);
		return f.renameTo(newFile);
	}

	/**
	 * 
	 * @param f
	 * @return
	 */
	public static String getName(File f) {
		String name = f.getName();
		if (name.lastIndexOf(".") != -1) {
			return name.substring(0, name.lastIndexOf("."));
		} else {
			return name;
		}
	}

	/**
	 * 获得单个文件扩展名
	 * 
	 * @param f
	 * @return
	 */
	public static String getExt(File f) {
		String name = f.getName();
		if (name.lastIndexOf(".") != -1) {
			return name.substring(name.lastIndexOf(".") + 1);
		} else {
			return "";
		}
	}

	public static String getDeepestFolderName(File f) {
		String abs = f.getAbsolutePath();
		if (f.isFile()) {
			String temp = abs.substring(0, abs.indexOf(f.getName()) - 1);
			if (temp.lastIndexOf(File.separator) != -1) {
				return temp.substring(temp.lastIndexOf(File.separator) + 1);
			} else {
				return "nofoldername";
			}
		}
		if (f.isDirectory()) {
			if (abs.lastIndexOf(File.separator) != -1) {
				return abs.substring(abs.lastIndexOf(File.separator) + 1);
			} else {
				return "nofoldername";
			}
		}
		return null;
	}

	/**
	 * 创建空文件
	 * 
	 * @param pathFile
	 * @return
	 */
	public static File createEmptyFile(String pathFile) {
		boolean b = createFolder(pathFile);
		File file = new File(pathFile);
		if (b && !file.exists()) {
			try {
				file.createNewFile();
			} catch (IOException e) {
				logger.error(ErrorUtil.getError(e));
			}
		}
		return file;
	}

	public static boolean createFolder(String pathFile) {
		String strFilePath = getPath(pathFile);
		File filePath = new File(strFilePath);
		boolean b = false;
		if (!filePath.exists()) {
			b = filePath.mkdirs();
		}
		return b;
	}

	/**
	 * 复制单个文件
	 * 
	 * @param oldPathFile
	 *            准备复制的文件源
	 * @param newPathFile
	 *            拷贝到新绝对路径带文件名
	 * @return
	 */
	public static File copyFile(String oldPathFile, String newPathFile) {
		File newFile = null;
		InputStream is = null;
		OutputStream os = null;
		try {
			File oldfile = new File(oldPathFile);
			if (oldfile.exists()) { // 文件存在时
				newFile = createEmptyFile(newPathFile);
				is = new FileInputStream(oldPathFile); // 读入原文件
				os = new FileOutputStream(newFile);
				byte[] buffer = new byte[1024];
				int bytesRead = 0;
				while ((bytesRead = is.read(buffer)) != -1) {
					os.write(buffer, 0, bytesRead);
				}
			}
		} catch (Exception e) {
			logger.error(ErrorUtil.getError(e));
		} finally {
			close(is, os);
		}
		return newFile;
	}

	/**
	 * 复制整个文件夹的内容
	 * 
	 * @param oldPath
	 *            准备拷贝的目录
	 * @param newPath
	 *            指定绝对路径的新目录
	 * @return
	 */
	public static void copyFolder(String oldPath, String newPath) {
		try {
			// 如果源文件夹不存在，直接返回.
			if (!new File(oldPath).exists()) {
				return;
			}
			new File(newPath).mkdirs(); // 如果文件夹不存在 则建立新文件夹
			File a = new File(oldPath);
			String[] file = a.list();
			File temp = null;
			for (int i = 0; i < file.length; i++) {
				if (oldPath.endsWith(File.separator)) {
					temp = new File(oldPath + file[i]);
				} else {
					temp = new File(oldPath + File.separator + file[i]);
				}
				if (temp.isFile()) {
					FileInputStream input = new FileInputStream(temp);
					FileOutputStream output = new FileOutputStream(newPath
							+ "/" + (temp.getName()).toString());
					byte[] b = new byte[1024 * 5];
					int len;
					while ((len = input.read(b)) != -1) {
						output.write(b, 0, len);
					}
					output.flush();
					output.close();
					input.close();
				}
				if (temp.isDirectory()) { // 如果是子文件夹
					copyFolder(oldPath + "/" + file[i], newPath + "/" + file[i]);
				}
			}
		} catch (Exception e) {
            logger.error(ErrorUtil.getError(e));
		}
	}

	public static void append(File filepath, String content) throws Exception {
		BufferedWriter bwr = null;
		FileWriter fw = null;
		try {
			fw = new FileWriter(filepath, true);
			bwr = new BufferedWriter(fw);
			bwr.write(content);
			bwr.newLine();
			bwr.flush();
			return;
		} catch (Exception e) {
			throw e;
		} finally {
			close(fw);
			close(bwr);
		}
	}

	public static void processFileByLine(File f, String encoding,
			ILineProcessor processor) throws Exception {
		FileInputStream fr = null;
		BufferedReader br = null;
		if (f.length() > 0) {
			try {
				fr = new FileInputStream(f);
				if (StringUtil.isNotEmpty(encoding)) {
					br = new BufferedReader(new InputStreamReader(fr, encoding));
				} else {
					br = new BufferedReader(new InputStreamReader(fr));
				}
				String tempStr = "";
				while ((tempStr = br.readLine()) != null
						&& processor.processLine(tempStr)) {
				}
			} catch (Exception e) {
				throw e;
			} finally {
				close(fr);
				close(br);
			}
		}
	}

	public static void main(String[] args) throws Exception {
		// String excludes =
		// ".jar,.rptdesign,.rpttemplate,.mex,.jpg,.gif,.JPG,.GIF,.bmp,.jpeg,.png,.zip,.rar,.db,.cab";
		// Collection cs2 = FileHelper.getFiles("c:/0625", excludes.split(","),
		// true);
		// System.out.println(cs2.size());
		// for (Iterator it = cs2.iterator(); it.hasNext();) {
		// File f = (File) it.next();
		// System.out.println(f.getName());
		// // f.delete();
		// }
		// MyFilenameFilter mff = new MyFilenameFilter(MyFilenameFilter.EQUALS);
		// mff.addExtension(".svn");
		// FileHelper.processFolders("c:/0625_BAK", new String[] { ".svn" },
		// new IFolderProcessor() {
		// public void processFolder(File f) {
		// System.gc();
		// System.out.println(f.getAbsolutePath());
		// // FileHelper.delFolder(f.getAbsolutePath());
		// }
		//
		// }, false);
		copyFile("c:/cb/com/1.txt", "c:/a/b/c/1.txt");
	}
}
